package com.shanjupay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.shanjupay.common.domain.BusinessException;
import com.shanjupay.common.domain.CommonErrorCode;
import com.shanjupay.common.util.AmountUtil;
import com.shanjupay.common.util.EncryptUtil;
import com.shanjupay.common.util.PaymentUtil;
import com.shanjupay.merchant.api.AppService;
import com.shanjupay.merchant.api.MerchantService;
import com.shanjupay.paymentagent.api.PayChannelAgentService;
import com.shanjupay.paymentagent.api.conf.AliConfigParam;
import com.shanjupay.paymentagent.api.dto.AlipayBean;
import com.shanjupay.paymentagent.api.dto.PaymentResponseDTO;
import com.shanjupay.transaction.api.PayChannelService;
import com.shanjupay.transaction.api.TransactionService;
import com.shanjupay.transaction.api.dto.PayChannelParamDTO;
import com.shanjupay.transaction.api.dto.PayOrderDTO;
import com.shanjupay.transaction.api.dto.QRCodeDto;
import com.shanjupay.transaction.convert.PayOrderConvert;
import com.shanjupay.transaction.entity.PayOrder;
import com.shanjupay.transaction.mapper.PayOrderMapper;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

/**
 * @program: shanjupay
 * @description:
 * @author: Mr.Hkc
 * @create: 2020-08-21 09:12
 **/

@Service
public class TransactionServiceImpl implements TransactionService {

    @Reference
    AppService appService;

    @Reference
    MerchantService merchantService;

    @Autowired
    PayOrderMapper payOrderMapper;

    @Reference
    PayChannelAgentService payChannelAgentService;


    @Autowired
    PayChannelService payChannelService;


    //从配置文件获取支付入口地址
    @Value("${shanjupay.payurl}")
    String payurl;

    /**
     * 生成门店二维码url
     *
     * @param qrCodeDto
     * @throws BusinessException
     * @returnString
     */
    public String createStoreQRCode(QRCodeDto qrCodeDto) throws BusinessException {

        //校验应用和门店
        verifyAppAndStore(qrCodeDto.getMerchantId(), qrCodeDto.getAppId(), qrCodeDto.getStoreId());
        //组装url所需要的参数
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setMerchantId(qrCodeDto.getMerchantId());
        payOrderDTO.setAppId(qrCodeDto.getAppId());
        payOrderDTO.setStoreId(qrCodeDto.getStoreId());
        payOrderDTO.setSubject(qrCodeDto.getSubject());//显示订单标题
        payOrderDTO.setChannel("shanju_c2b");//服务类型
        payOrderDTO.setBody(qrCodeDto.getBody());//订单内容
        //转成json
        String jsonString = JSON.toJSONString(payOrderDTO);
        //将支付信息保存到票据中
        String ticket = EncryptUtil.encodeUTF8StringBase64(jsonString);
        //目标是生成一个支付入口的url,需要携带参数传入的参数转成json,用base64进行编码
        String url = payurl + ticket;
        return url;
    }

    /**
     * @param payOrderDTO
     * @return
     * @throws BusinessException
     */
    public PaymentResponseDTO submitOrderByAli(PayOrderDTO payOrderDTO) throws BusinessException {
        //支付渠道
        payOrderDTO.setChannel("ALIPAY_WAP");
        //1.保存订单到数据库
        PayOrderDTO save = save(payOrderDTO);
        //2.调用支付渠道代理服务,调用支付宝下单
        return alipayH5(save.getTradeNo());
    }

    /**
     * 调用支付渠道代理服务,调用支付宝下单
     *
     * @param tradeNo
     * @return
     */
    private PaymentResponseDTO alipayH5(String tradeNo) {

        //订单信息->从数据库查
        PayOrderDTO payOrderDTO = queryPayOrder(tradeNo);
        //组装alipaybean 订单参数
        AlipayBean alipayBean = new AlipayBean();
        alipayBean.setOutTradeNo(payOrderDTO.getTradeNo());
        try {
            alipayBean.setTotalAmount(AmountUtil.changeF2Y(payOrderDTO.getTotalAmount().toString()));
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(CommonErrorCode.E_300006);
        }
        alipayBean.setSubject(payOrderDTO.getSubject());
        alipayBean.setBody(payOrderDTO.getBody());
        alipayBean.setExpireTime("30m");

        //支付渠道配置参数->从数据库查
        //String appId,String platformChannel,String payChannel
        PayChannelParamDTO payChannelParamDTO = payChannelService.queryParamByAppPlatformAndPayChannel(payOrderDTO.getAppId(), "shanju_c2b", "ALIPAY_WAP");
        String paramJson = payChannelParamDTO.getParam();
        //支付渠道参数
        AliConfigParam aliConfigParam = JSON.parseObject(paramJson, AliConfigParam.class);
        //字符编码
        aliConfigParam.setCharest("utf-8");
        PaymentResponseDTO payOrderByAliWAP = payChannelAgentService.createPayOrderByAliWAP(aliConfigParam, alipayBean);
        return payOrderByAliWAP;
    }


    /**
     * 根据订单号查询订单信息
     *
     * @param tradeNo
     * @return
     */
    public PayOrderDTO queryPayOrder(String tradeNo) {
        PayOrder payOrder = payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>()
                .eq(PayOrder::getTradeNo, tradeNo));
        return PayOrderConvert.INSTANCE.entity2dto(payOrder);
    }


    /**
     * 保存订单
     *
     * @param payOrderDTO
     * @return
     * @throws BusinessException
     */
    private PayOrderDTO save(PayOrderDTO payOrderDTO) throws BusinessException {
        PayOrder entity = PayOrderConvert.INSTANCE.dto2entity(payOrderDTO);
        entity.setTradeNo(PaymentUtil.genUniquePayOrderNo());
        //订单创建时间
        entity.setCreateTime(LocalDateTime.now());
        //设置过期时间,30分钟
        entity.setExpireTime(LocalDateTime.now().plus(30, ChronoUnit.MINUTES));
        entity.setCurrency("CNY"); //设置支付货币
        entity.setTradeState("0"); //订单状态
        payOrderMapper.insert(entity);
        return PayOrderConvert.INSTANCE.entity2dto(entity);
    }

    /**
     * 校验应用和门店是否属于当前登录商户
     *
     * @param merchantId
     * @param appId
     * @param storeId
     */
    private void verifyAppAndStore(Long merchantId, String appId, Long storeId) throws BusinessException {
        //判断应用是否属于当前商户
        Boolean containApp = appService.queryAppInMerchant(appId, merchantId);
        if (!containApp) {
            throw new BusinessException(CommonErrorCode.E_200005);
        }
        //校验门店是否属于商户
        Boolean containStore = merchantService.queryStoreInMerchant(storeId, merchantId);
        if (!containStore) {
            throw new BusinessException(CommonErrorCode.E_200006);
        }
    }

}

